package com.itheima.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.itheima.mapper.*;
import com.itheima.pojo.DTO.MemberDataDTO;
import com.itheima.pojo.HotSetmeal;
import com.itheima.pojo.Order;
import com.itheima.pojo.OrderSetting;
import com.itheima.pojo.SetmealCount;
import com.itheima.pojo.VO.BusinessDataVO;
import com.itheima.pojo.VO.MemberDataVO;
import com.itheima.pojo.VO.SetmealDataVO;
import com.itheima.service.ReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderSettingMapper orderSettingMapper;
    @Autowired
    private OrderMapper orderMapper;

    @Override
    public MemberDataVO getMemberReport() {
        LocalDate currentDate = LocalDate.now();
        List<MemberDataDTO> date = new ArrayList<>();
        for (int i = 24; i >= 1; i--) {
            // 计算目标月份（当前月向前推 i 个月）
            YearMonth targetMonth = YearMonth.from(currentDate).minusMonths(i);

            // 获取该月的第一天和最后一天（LocalDate）
            LocalDate firstDay = targetMonth.atDay(1);
            LocalDate lastDay = targetMonth.atEndOfMonth();
            date.add(new MemberDataDTO(firstDay, lastDay));
        }


        List<Integer> countList = new ArrayList<>();
        List<String> monthList = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd");
        for (MemberDataDTO dto : date){
            Integer count = memberMapper.getCountByDate(dto);
            String month = formatter.format(dto.getEndDate());
            countList.add(count);
            monthList.add(month);
        }

        return MemberDataVO.builder().months(monthList).memberCount(countList).build();
    }

    @Override
    public SetmealDataVO getSetmealReport() {
        List<SetmealCount> setmealCounts = setmealMapper.getSetmealCount();
        List<String> setmealNames = setmealCounts.stream().map(SetmealCount::getName).collect(Collectors.toList());
        return SetmealDataVO.builder()
                .setmealNames(setmealNames)
                .setmealCount(setmealCounts)
                .build();
    }

    @Override
    public BusinessDataVO getBusinessReportData() {
        BusinessDataVO businessDataVO = new BusinessDataVO();
        LocalDate currentDate = LocalDate.now();
        LocalDate thisWeek = currentDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        LocalDate thisMonth = currentDate.with(TemporalAdjusters.firstDayOfMonth());
        //  数据日期
        businessDataVO.setReportDate(currentDate.toString());

        //  总会员数
        businessDataVO.setTotalMember(memberMapper.getCountByDate(new MemberDataDTO(null, currentDate)));

        //  今日新增会员数
        businessDataVO.setTodayNewMember(memberMapper.getCountByDate(new MemberDataDTO(currentDate, currentDate)));
        //  今日预约数
        OrderSetting todayOrderSetting = orderSettingMapper.getOrderSettingByDate(currentDate);
        businessDataVO.setTodayOrderNumber(todayOrderSetting.getReservations());
        //  今日到诊数
        businessDataVO.setTodayVisitsNumber(orderMapper.getVisitNumberByDate(currentDate, currentDate, Order.ORDERSTATUS_YES));
        //  本周新增会员数
        businessDataVO.setThisWeekNewMember(memberMapper.getCountByDate(new MemberDataDTO(thisWeek, currentDate)));
        //  本周预约数
        List<OrderSetting> thisWeekOrderSetting = orderSettingMapper.getOrderSettingByMonth(thisWeek, currentDate);
        businessDataVO.setThisWeekOrderNumber(thisWeekOrderSetting.stream().mapToInt(OrderSetting::getReservations).sum());
        //  本周到诊数
        businessDataVO.setThisWeekVisitsNumber(orderMapper.getVisitNumberByDate(thisWeek, currentDate, Order.ORDERSTATUS_YES));
        //  本月新增会员数
        businessDataVO.setThisMonthNewMember(memberMapper.getCountByDate(new MemberDataDTO(thisMonth, currentDate)));
        //  本月预约数
        List<OrderSetting> thisMonthOrderSetting = orderSettingMapper.getOrderSettingByMonth(thisMonth, currentDate);
        businessDataVO.setThisMonthOrderNumber(thisMonthOrderSetting.stream().mapToInt(OrderSetting::getReservations).sum());
        //  本月到诊数
        businessDataVO.setThisMonthVisitsNumber(orderMapper.getVisitNumberByDate(thisMonth, currentDate, Order.ORDERSTATUS_YES));

        //  热门套餐
        List<SetmealCount> setmealCounts = setmealMapper.getSetmealCount();
        Integer totalCount = setmealCounts.stream().mapToInt(SetmealCount::getValue).sum();
        List<HotSetmeal> hotSetmeal = setmealCounts.stream().map(setmealCount -> HotSetmeal.builder()
                .setmeal_count(setmealCount.getValue())
                .name(setmealCount.getName())
                .proportion(setmealCount.getValue() * 1.0 / totalCount)
                .build()).collect(Collectors.toList());
        businessDataVO.setHotSetmeal(hotSetmeal);

        return businessDataVO;
    }

    @Override
    public void exportBusinessReport(HttpServletResponse response){
        TemplateExportParams params = new TemplateExportParams("templates/report_template.xlsx");
        BusinessDataVO businessDataVO = getBusinessReportData();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("reportDate", businessDataVO.getReportDate());
        map.put("totalMember", businessDataVO.getTotalMember());
        map.put("todayNewMember", businessDataVO.getTodayNewMember());
        map.put("thisWeekNewMember", businessDataVO.getThisWeekNewMember());
        map.put("thisMonthNewMember", businessDataVO.getThisMonthNewMember());
        map.put("todayOrderNumber", businessDataVO.getTodayOrderNumber());
        map.put("thisWeekOrderNumber", businessDataVO.getThisWeekOrderNumber());
        map.put("thisMonthOrderNumber", businessDataVO.getThisMonthOrderNumber());
        map.put("todayVisitsNumber", businessDataVO.getTodayVisitsNumber());
        map.put("thisWeekVisitsNumber", businessDataVO.getThisWeekVisitsNumber());
        map.put("thisMonthVisitsNumber", businessDataVO.getThisMonthVisitsNumber());
        List<Map<String, Object>> listmap = new ArrayList<Map<String, Object>>();
        for (HotSetmeal hotSetmeal : businessDataVO.getHotSetmeal()){
            Map<String, Object> hotSetmealMap = new HashMap<String, Object>();
            hotSetmealMap.put("name", hotSetmeal.getName());
            hotSetmealMap.put("setmeal_count", hotSetmeal.getSetmeal_count());
            hotSetmealMap.put("proportion", hotSetmeal.getProportion());
            hotSetmealMap.put("remark", null);
            listmap.add(hotSetmealMap);
        }
        map.put("hotSetmeal", listmap);

        try (Workbook workbook = ExcelExportUtil.exportExcel(params, map)){
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            String filename = "report.xlsx";
            String encodedFileName = URLEncoder.encode(filename, "UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"; filename*=UTF-8''" + encodedFileName);
            workbook.write(response.getOutputStream());
        }catch (IOException e) {
            log.error("文件写入失败", e);
        } catch (Exception e) {
            log.error("报表导出异常", e);
            throw new RuntimeException("系统错误", e);
        }
    }
}
